/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package taskmanager2ndedition.client;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import taskmanager2ndedition.*;
import java.util.*;
import taskmanager2ndedition.Connection;
import taskmanager2ndedition.GUI.ErrorForm;
import taskmanager2ndedition.GUI.TaskManager2ndEditionView;

/**
 *
 * @author denaas
 */
public class ClientController {

    private int userId = 0;
    private CmdInterpretator cmdInterpretator;
    private Connection connection;
    private int checkPeriod = 1000;
    private int updatePeriod = 15000;
    private boolean taskListModified = false;
    private boolean userListModified = false;
    private boolean newed = false;
    private ClientTaskManager taskManager;
    private ClientUserManager userManager;
    private TaskMonitor monitor;
    private boolean admin;
    
    public ClientController(){
        AlarmManagerFactory factory = new SimpleAlarmManagerFactory(this);
        monitor = new TaskMonitor(factory.createInstance(), this);
        Thread taskMonitor = new Thread(monitor);
        taskMonitor.start();
        cmdInterpretator = new CmdInterpretator();
    }
    
    public boolean isTaskListModified(){
        return taskListModified;
    }
    
    public synchronized void setTaskListModified(boolean val){
        while (newed)
            try {
            wait();
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        }
        newed = true;
        taskListModified = val;
        newed = false;
    }
    
    public boolean isUserListModified(){
        return userListModified;
    }
    
    public synchronized void setUserListModified(boolean val){
        while (newed)
            try {
            wait();
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        }
        newed = true;
        userListModified = val;
        newed = false;
    }

    public int getUpdatePeriod(){
        return updatePeriod;
    }
    
    public void setUpdatePeriod(int val){
        updatePeriod = val;
    }
    
    public int getCheckPeriod(){
        return checkPeriod;
    }
    
    public void setCheckPeriod(int val){
        checkPeriod = val;
    }
    
    public int getUserId(){
        return userId;
    }
    
    public synchronized void setUserId(int val){
        userId = val;
    }

    public void showErrorMessage(String message) {
        ErrorForm error = new ErrorForm(message);
        error.setVisible(true);
    }

    public void changePassword(String oldPassword, String newPassword) {
        try {
            List params = new LinkedList();
            params.add(oldPassword);
            params.add(newPassword);

            String request = cmdInterpretator.generateRequest(new Cmd("changePassword", params));
            String responce = connection.send(request);
            cmdInterpretator.performResponce(responce);
        } catch (Exception ex) {
            showErrorMessage(ex.getMessage());
            ex.printStackTrace();
        }
    }

    public void addTask(ClientTaskInfo task) {
        try {
            List params = new LinkedList();
            ((Task)task).setUserId(userId);
            params.add((Task)task);

            String request = cmdInterpretator.generateRequest(new Cmd("addTask", params));
            String responce = connection.send(request);
            cmdInterpretator.performResponce(responce);
        } catch (Exception ex) {
            showErrorMessage(ex.getMessage());
            ex.printStackTrace();
        }
    }

    public void deleteUser(int userId) {
        try {
            List params = new LinkedList();
            params.add(userId);

            String request = cmdInterpretator.generateRequest(new Cmd("deleteUser", params));
            String responce = connection.send(request);
            cmdInterpretator.performResponce(responce);
        } catch (Exception ex) {
            showErrorMessage(ex.getMessage());
            ex.printStackTrace();
        }
    }

    public void editTask(ClientTaskInfo task) {
        try {
            List params = new LinkedList();
            ((Task)task).setUserId(userId);
            params.add((Task)task);

            String request = cmdInterpretator.generateRequest(new Cmd("editTask", params));
            String responce = connection.send(request);
            cmdInterpretator.performResponce(responce);
        } catch (Exception ex) {
            showErrorMessage(ex.getMessage());
            ex.printStackTrace();
        }
    }

    public String getUserLogin() {
        try {
            List params = new LinkedList();

            String request = cmdInterpretator.generateRequest(new Cmd("getUserLogin", params));
            String responce = connection.send(request);
            String result = (String)cmdInterpretator.performResponce(responce);
            if (result == null)
                return "";
            return result;
        } catch (Exception ex) {
            showErrorMessage(ex.getMessage());
            ex.printStackTrace();
        }
        return null;
    }

    private Boolean isAdmin_s() {
        try {
            List params = new LinkedList();

            String request = cmdInterpretator.generateRequest(new Cmd("isAdmin", params));
            String responce = connection.send(request);
            Boolean result = (Boolean) cmdInterpretator.performResponce(responce);
            if (result == null)
                return false;
            return result;
        } catch (Exception ex) {
            showErrorMessage(ex.getMessage());
            ex.printStackTrace();
        }

        return null;
    }
    
    public boolean isAdmin(){
        return admin;
    }

    public boolean login(String login, String password) {
        try {
            connection = new ClientConnection("localhost", 5555);            
            cmdInterpretator.setConnection(connection);
                
            List params = new LinkedList();
            params.add(login);
            params.add(password);

            String request = cmdInterpretator.generateRequest(new Cmd("login", params));
            String responce = connection.send(request);
            startSession((Integer) cmdInterpretator.performResponce(responce));            
        } catch (Exception ex) {
            showErrorMessage(ex.getMessage());            
            ex.printStackTrace();
            return false;
        }
        return true;
    }
    
    private void startSession(int id){
        setUserId(id);                
        admin = isAdmin_s();
        taskManager = new ClientTaskManager(this);
        userManager = new ClientUserManager(this);
        monitor.setTaskList(taskManager.getTasks());
    }
    
    private void closeSession(){  
        setUserId(0); 
        admin = false;
        monitor.setTaskList(null);
        taskManager.finalize();
        userManager.finalize();
    }

    public void logout() {
        try {            
            closeSession();
            List params = new LinkedList();

            String request = cmdInterpretator.generateRequest(new Cmd("logout", params));
            String responce = connection.send(request);
            cmdInterpretator.performResponce(responce);  
            connection = null;
            cmdInterpretator.setConnection(null);
        } catch (Exception ex) {
            showErrorMessage(ex.getMessage());
            ex.printStackTrace();
        }
    }

    public void register(String login, String password) {
        try {
            boolean hasConnection = connection != null;
            if (!hasConnection){
                connection = new ClientConnection("localhost", 5555);            
                cmdInterpretator.setConnection(connection);
            }
            List params = new LinkedList();
            params.add(login);
            params.add(password);

            String request = cmdInterpretator.generateRequest(new Cmd("register", params));
            String responce = connection.send(request);
            cmdInterpretator.performResponce(responce);
            if (!hasConnection){
                connection = null;            
                cmdInterpretator.setConnection(null);
            }
        } catch (Exception ex) {
            showErrorMessage(ex.getMessage());
            ex.printStackTrace();
        }
    }

    public void addUser(String login, String password) {
        try {
            List params = new LinkedList();
            params.add(login);
            params.add(password);

            String request = cmdInterpretator.generateRequest(new Cmd("addUser", params));
            String responce = connection.send(request);
            cmdInterpretator.performResponce(responce);
        } catch (Exception ex) {
            showErrorMessage(ex.getMessage());
            ex.printStackTrace();
        }
    }

    public void removeTask(ClientTaskInfo task) {
        try {
            List params = new LinkedList();
            ((Task)task).setUserId(userId);
            params.add((Task)task);

            String request = cmdInterpretator.generateRequest(new Cmd("removeTask", params));
            String responce = connection.send(request);
            cmdInterpretator.performResponce(responce);
        } catch (Exception ex) {
            showErrorMessage(ex.getMessage());
            ex.printStackTrace();
        }
    }

    public List<ClientTaskInfo> updateTasks() {
        try {
            List params = new LinkedList();
            params.add(userId);

            String request = cmdInterpretator.generateRequest(new Cmd("updateTasks", params));
            String responce = connection.send(request);
            List result =  (List<Task>) cmdInterpretator.performResponce(responce);
            if (result == null)
                return new LinkedList<ClientTaskInfo>();
            return result;
        } catch (Exception ex) {
            showErrorMessage(ex.getMessage());
            ex.printStackTrace();
        }

        return null;
    }

    public List<ClientTaskInfo> getAllTasks() {
        try {
            List params = new LinkedList();
            params.add(userId);

            String request = cmdInterpretator.generateRequest(new Cmd("getAllTasks", params));
            String responce = connection.send(request);
            List result = (List<Task>) cmdInterpretator.performResponce(responce);
            if (result == null)
                return new LinkedList<ClientTaskInfo>();
            return result;
        } catch (Exception ex) {
            showErrorMessage(ex.getMessage());
            ex.printStackTrace();
        }

        return null;
    }

    public List<ClientTaskInfo> getTasksOnDate(java.util.Date date) {
        return taskManager.getTasksOnDate(date);
    }

//------------------------------------------------------------------------------
    public ClientTaskInfo findTaskById(int id) {
        return taskManager.findById(id);
    }

    public void closeTask(int id) {
        Task task = (Task)findTaskById(id);
        if (task == null)
            return;
        
        task.setStatus(TaskInfo.TaskStatus.Closed);
        editTask(task);        
    }
    
    public void setTaskInProgress(int id){
        Task task = (Task)findTaskById(id);
        if (task == null)
            return;
        
        task.setStatus(TaskInfo.TaskStatus.InProgress);
        editTask(task);
    }

    public void postponeTask(int id, int delay) {
        Task task = (Task)findTaskById(id);
        if (task == null)
            return;
        
        Calendar cl = new GregorianCalendar();
        cl.setTime(task.getExpirationDate());
        cl.add(Calendar.MINUTE, delay);
        
        task.setExpirationDate(new java.util.Date(cl.getTime().getTime()));
        
        editTask(task);        
    }
//------------------------------------------------------------------------------    
    
    public List<ClientUserInfo> updateUsers() {
        try {
            List params = new LinkedList();

            String request = cmdInterpretator.generateRequest(new Cmd("updateUsers", params));
            String responce = connection.send(request);
            List result = (List<User>) cmdInterpretator.performResponce(responce);
            if (result == null)
                return new LinkedList<ClientUserInfo>();
            return result;
        } catch (Exception ex) {
            showErrorMessage(ex.getMessage());
            ex.printStackTrace();
        }

        return null;
    }

    public StatisticInfo updateStatistics() {
        try {
            List params = new LinkedList();
            params.add(userId);

            String request = cmdInterpretator.generateRequest(new Cmd("updateStatistics", params));
            String responce = connection.send(request);
            StatisticInfo result = (StatisticInfo) cmdInterpretator.performResponce(responce);
            if (result == null)
                return new StatisticInfo();
            return result;
        } catch (Exception ex) {
            showErrorMessage(ex.getMessage());
            ex.printStackTrace();
        }

        return null;
    }

    public Boolean validateDate(java.util.Date date) {
        try {
            List params = new LinkedList();
            params.add(userId);
            params.add(date);

            String request = cmdInterpretator.generateRequest(new Cmd("validateDate", params));
            String responce = connection.send(request);
            Boolean result = (Boolean) cmdInterpretator.performResponce(responce);
            if (result == null)
                return false;
            return result;
        } catch (Exception ex) {
            showErrorMessage(ex.getMessage());
            ex.printStackTrace();
        }
        return null;
    }
    
    public List<ClientUserInfo> getAllUsers(){
        try {
            List params = new LinkedList();

            String request = cmdInterpretator.generateRequest(new Cmd("getAllUsers", params));
            String responce = connection.send(request);
            List result = (List<User>) cmdInterpretator.performResponce(responce);
            if (result == null)
                return new LinkedList<ClientUserInfo>();
            return result;
        } catch (Exception ex) {
            showErrorMessage(ex.getMessage());
            ex.printStackTrace();
        }

        return null;
    }
    
    public List<ClientUserInfo> getUsers(){
        return userManager.getUsers();
    }
    
    public List<ClientTaskInfo> getTasks(){
        return taskManager.getTasks();
    }
    
     public void forceUpdateUsers(){
        userManager.forceUpdate();
    }
    
    public void forceUpdateTasks(){
        taskManager.forceUpdate();
    }
}
